package com.jeez.common.security;

public class Base64Code {
	private static final byte[] _encode_map = { 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98,
			99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54,
			55, 56, 57, 43, 47 };

	private static byte[] _decode_map = new byte[''];

	static {
		for (int i = 0; i < _encode_map.length; ++i)
			_decode_map[_encode_map[i]] = (byte) i;
	}

	public static final byte[] encode(byte[] data) {
		if (data == null)
			return null;
		byte[] dest = new byte[(data.length + 2) / 3 * 4];
		int data_len = data.length - 2;
		int i = 0;
		int j = 0;
		for (; i < data_len; i += 3) {
			dest[(j++)] = _encode_map[(data[i] >>> 2 & 0x3F)];
			dest[(j++)] = _encode_map[(data[(i + 1)] >>> 4 & 0xF | data[i] << 4 & 0x3F)];
			dest[(j++)] = _encode_map[(data[(i + 2)] >>> 6 & 0x3 | data[(i + 1)] << 2 & 0x3F)];
			dest[(j++)] = _encode_map[(data[(i + 2)] & 0x3F)];
		}

		if (i < data.length) {
			dest[(j++)] = _encode_map[(data[i] >>> 2 & 0x3F)];
			if (i < data.length - 1) {
				dest[(j++)] = _encode_map[(data[(i + 1)] >>> 4 & 0xF | data[i] << 4 & 0x3F)];
				dest[(j++)] = _encode_map[(data[(i + 1)] << 2 & 0x3F)];
			} else {
				dest[(j++)] = _encode_map[(data[i] << 4 & 0x3F)];
			}
		}
		for (; j < dest.length; ++j) {
			dest[j] = 61;
		}
		return dest;
	}

	public static final byte[] decode(byte[] data) {
		if (data == null)
			return null;
		int ending = data.length;
		if (ending < 1)
			return null;
		while (data[(--ending - 1)] == 61)
			;
		byte[] dest = new byte[ending - data.length / 4];

		for (int i = 0; i < data.length; ++i) {
			data[i] = _decode_map[data[i]];
		}
		int dest_len = dest.length - 2;
		int i = 0;
		int j ;
		for ( j = 0; j < dest_len; j += 3) {
			dest[j] = (byte) (data[i] << 2 & 0xFF | data[(i + 1)] >>> 4 & 0x3);
			dest[(j + 1)] = (byte) (data[(i + 1)] << 4 & 0xFF | data[(i + 2)] >>> 2 & 0xF);
			dest[(j + 2)] = (byte) (data[(i + 2)] << 6 & 0xFF | data[(i + 3)] & 0x3F);
			i += 4;
		}

		if (j < dest.length)
			dest[j] = (byte) (data[i] << 2 & 0xFF | data[(i + 1)] >>> 4 & 0x3);
		if (++j < dest.length)
			dest[j] = (byte) (data[(i + 1)] << 4 & 0xFF | data[(i + 2)] >>> 2 & 0xF);
		return dest;
	}

}
